package com.turtle3d.formallanguage.symbol;

import java.util.HashMap;
import java.util.Hashtable;

import com.turtle3d.App;

/**
 * SymbolFactory is a singleton. Use it to ensure that you don't duplicate SymbolClasses and to
 * create them in convinient way.
 * 
 * @author Marek Paterczyk <marek.paterczyk@gmail.com>
 *
 */
public class SymbolFactory
{
	private HashMap<String, SymbolClass> symbolClasses = new HashMap<String, SymbolClass>();
	
	/**
	 * If a method needs a parameter that is not defined in orginating symbol,
	 * it takes default one.
	 */
	private Hashtable<String, Float> defaultParameters = new Hashtable<String, Float>();
	
	private static SymbolFactory symbolFactory = null;
	
	public SymbolFactory()
	{
		setParameter(Symbol.RADIUS, 0.02f);	
		setParameter(Symbol.DISTANCE, 0.2f);		
		setParameter(Symbol.VARIATION, 5f);
		setParameter(Symbol.TURN_ANGLE, 30f);
		setParameter(Symbol.PITCH_ANGLE, 30f);
		setParameter(Symbol.ROLL_ANGLE, 90f);
		setParameter(Symbol.SCALE_MULTIPLIER, 1f);		
	}		
	
	/**
	 * Register a SymbolClass.
	 * 
	 * @param symbolClass
	 * @return true if was added (didn't exist)
	 */
	public boolean registerSymbolClass(SymbolClass symbolClass){
		if(symbolClasses.containsKey(symbolClass.getSymbolClassName()))
			return false;
		
		symbolClasses.put(symbolClass.getSymbolClassName(), symbolClass);
		return true;
	}
	
	public boolean registerSymbolClass(String symbol, String symbolClassName, Method method){
	 return registerSymbolClass(new SymbolClass(symbol, symbolClassName, method));
	}
	
	/**
	 * Gets previously registered SymbolClass or creates (registers) it if it doesn't exist.
	 * @param symbolClassName
	 * @return SymbolClass of desired name.
	 */
	public SymbolClass getSymbolClass(String symbolClassName){
		if(symbolClasses.containsKey(symbolClassName))
			return symbolClasses.get(symbolClassName);				
		
		return new SymbolClass(symbolClassName);
		
	}
	
	/**
	 * Creates a new Symbol. If SymbolClass with symbolClassName doesn't exist,
	 * it is created and registered.
	 * @param symbolClassName 
	 * @return Created symbol
	 */
	public Symbol createSymbolofClass(String symbolClassName){		
		SymbolClass symbolClass = getSymbolClass(symbolClassName);
					
		Symbol symbol = new Symbol(symbolClass);		
		
		return symbol;
	}
	
	public static SymbolFactory getSymbolFactory(){
		if(symbolFactory==null){
			symbolFactory = new SymbolFactory();			
		}
		
		return symbolFactory;
	}
	
	public void setParameter(String name, Float value){
		if(value==null)
			defaultParameters.remove(name);
		else
			defaultParameters.put(name, value);
	}
	
	public Float getParameter(String name){
		if(!defaultParameters.containsKey(name)){
			App.printlnError(name+" parameter is not defined!");
		}
		
		return defaultParameters.get(name);
	}		
	
	public boolean defaultParameterExists(String name){
		return defaultParameters.contains(name);
	}

	public Hashtable<String, Float> getDefaultParameters(){
		return defaultParameters;
	}
	
	public static void reset(){
		symbolFactory = null;
	}
	
	
}
